// -*-mode:c++; coding:utf-8-*-

#include <boost/foreach.hpp>

#include <logger.hpp>
#include <performance_measurement.hpp>

#include "memory_table_scanner.hpp"

namespace xbase
{
	// 若传入的块为空，则从当前正在使用的内存表中取出第一个块进行替
	// 换，并继续读取操作。
	// 
	// 若发现传入的块已经读完，则通过该块的行名，找到下一个要读的
	// 块，进行替换
	// 
	// 以上保证了块不为空，现在则读取该块内的指定索引开始的满足条件
	// 的记录，返回时索引正是下一条记录的索引，保证了m_entry_index
	// 的语义
	//
	// 若读完，则返回false
	bool memory_table_scanner::next_entry(impl_map_scan_state &impl_scan_state) const
	{
		MEASUREMENT_OF_TIME("memory_table_scanner::next_entry", this->id());
		
		for(;;) {
			if((! impl_scan_state.m_row_block)	// 当前块为空
			   || (impl_scan_state.m_entry_index
			       >= impl_scan_state.m_row_block->block_index().size())) // 或若当前块已经用完
			{
				if(impl_scan_state.m_need_check_lock) // update check lock state
				{
					impl_scan_state.m_need_check_lock
						= m_memtable->is_working_table(impl_scan_state.m_table);
				}

				bool ok = false;

				if(impl_scan_state.m_need_check_lock) // locked version
				{
					//Guard<ReadWriteLock::ReadLock> guard(m_memtable->working_table_lock().read_lock());
					boost::shared_lock<boost::shared_mutex> guard(m_memtable->working_table_lock());
					
					ok = next_block_no_lock(impl_scan_state);
				}
				else	// non-locked version
				{
					ok = next_block_no_lock(impl_scan_state);
				}

				if(! ok) // end
				{
					LOG(DEBUG, "memory_table_scanner::next_entry cur map_table scan end");
					return false;
				}
			}

			const block_index_type &block_index = impl_scan_state.m_row_block->block_index();
			assert(block_index.empty() == false); // 块不为空
			
			// 一个块的行是同一行，所以对一个块，只检查一次行即可
			//
			// TODO: 这里可以加入状态，只有行改变后，才检查该行是否越界，如：
			// if(impl_scan_state.m_row_changed) {... is_reached_end_row ...}
			const block_entry &first_entry = block_index[impl_scan_state.m_entry_index];
			if(scan_context_ptr()->is_reached_end_row(*first_entry.m_key->row()))
			{
				return false;
			}
			for(; impl_scan_state.m_entry_index < block_index.size();
			    ++impl_scan_state.m_entry_index)
			{
				const block_entry &cur_entry = block_index[impl_scan_state.m_entry_index];
				// 交由上层过滤
				// if(scan_context_ptr()->is_contain_timestamp(cur_entry.m_key->timestamp()->get())
				//    && scan_context_ptr()->is_contain_column(*cur_entry.m_key->column()))
				if(true)
				{
					impl_scan_state.m_entry = cur_entry; // save it!
					// 将索引指向下一条记录，以准备好下一次调用。这也是它的语义：总指向下一次要读取的索引位置
					++impl_scan_state.m_entry_index;
					return true; // 然后必须在此返回！
				}
			}
			// 若到此，则说明这个块内没找到符合条件的数据，则会转到下一个块继续找，直到找到一个符合条件的，或扫描完。
		}
		
		return true;	// never goes here, just make compiler happy
	}

	bool memory_table_scanner::lower_bound(impl_map_scan_state &impl_scan_state,
					       const key_wrapper *key) const
	{
		if(impl_scan_state.m_need_check_lock) // update check lock state
		{
			impl_scan_state.m_need_check_lock
				= m_memtable->is_working_table(impl_scan_state.m_table);
		}
		
		bool ok = false;
		row_block::pointer next_row_block; // 以防当前行内lower_bound没有的话，则用下一行
		
		if(impl_scan_state.m_need_check_lock) // locked version
		{
			//Guard<ReadWriteLock::ReadLock> guard(m_memtable->working_table_lock().read_lock());
			boost::shared_lock<boost::shared_mutex> guard(m_memtable->working_table_lock());
			ok = lower_bound_row_no_lock(impl_scan_state, next_row_block, key);
		}
		else		// non-locked version
		{
			ok = lower_bound_row_no_lock(impl_scan_state, next_row_block, key);
		}

		if(! ok)
		{
			LOG(DEBUG, "memory_table_scanner::lower_bound lower bound row \""
			    << dump_string_char(*key->row())
			    << "\" return end");
			BOOST_FOREACH(const memory_table::impl_map_type::value_type & elem, *impl_scan_state.m_table)
			{
				LOG(DEBUG, "memory table row: "
				    << dump_string_char(*elem.first));
				(void)elem;
			}
			return false;
		}

		// 找到要找的Key在给定行块中的哪一条索引上
		const block_index_type &block_index = impl_scan_state.m_row_block->block_index();
		assert(block_index.empty() == false);

		const block_index_type::const_iterator iter_end = block_index.end();
		block_index_type::const_iterator iter = std::lower_bound(block_index.begin(),
									 iter_end,
									 key,
									 row_block::entry_less_than());
		if(iter_end == iter) // 在当前行中没有找到，则下一个行块的第一条一定满足！
		{
			if(! next_row_block) // 这个已经是最后一个行块了，没有下一个块，则返回结束
			{
				LOG(DEBUG, "memory_table_scanner::lower_bound lower bound key return end, "
				    << "and this is last row block, return end");
				return false;
			}
			LOG(DEBUG, "memory_table_scanner::lower_bound lower bound key return end, "
			    << "use next row block instead");
			impl_scan_state.m_row_block = next_row_block;
			impl_scan_state.m_entry_index = 0;
		}
		else		// 找到
		{
			impl_scan_state.m_entry_index = (iter - block_index.begin());
		}

		return true;
	}

} // namespace xbase
